package org.jeecg.modules.business.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.val;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.business.dto.CouponsGenerateDto;
import org.jeecg.modules.business.dto.MobileDto;
import org.jeecg.modules.business.dto.ProvideCouponsUsedDto;
import org.jeecg.modules.business.entity.BusMarketCoupons;
import org.jeecg.modules.business.entity.BusMarketCouponsUsed;
import org.jeecg.modules.business.entity.BusMemberCard;
import org.jeecg.modules.business.enums.CouponsStatusEnum;
import org.jeecg.modules.business.mapper.BusMarketCouponsMapper;
import org.jeecg.modules.business.mapper.BusMarketCouponsUsedMapper;
import org.jeecg.modules.business.service.IBusMarketCouponsUsedService;
import org.jeecg.modules.system.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @Description: 免房券领取使用表
 * @Author: jeecg-boot
 * @Date:   2023-03-09
 * @Version: V1.0
 */
@Service
public class BusMarketCouponsUsedServiceImpl extends ServiceImpl<BusMarketCouponsUsedMapper, BusMarketCouponsUsed> implements IBusMarketCouponsUsedService {
    @Resource
    private BusMarketCouponsUsedMapper busMarketCouponsUsedMapper;

    @Resource
    private BusMarketCouponsMapper busMarketCouponsMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private BusMemberCardServiceImpl busMemberCardService;
    /**
     * 生成16位数字+prefix
     * @param prefix
     * @return
     */
    private String randomNumber(String prefix) {
        int first = new Random(10).nextInt(8) + 1;
        int hashCode = UUID.randomUUID().toString().hashCode();
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        return prefix + first + String.format("%015d", hashCode);
    }

    /**
     * 生成免房券领取使用
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result generate(CouponsGenerateDto dto){
        if(ObjectUtils.isEmpty(dto.getCouponsId())) return Result.error("免房券id不能为空");
        if(dto.getNum()<=0) return Result.error("生成数量不能小于1!");
       BusMarketCoupons coupons=busMarketCouponsMapper .selectById(dto.getCouponsId());
        if(ObjectUtils.isEmpty(coupons)) {
           return Result.error("免房券活动不存在");
       }
        List<BusMarketCouponsUsed> busMarketCouponsUsedList = new ArrayList<>();
        while (dto.getNum()>0){
            BusMarketCouponsUsed busMarketCouponsUsed =new BusMarketCouponsUsed();
            busMarketCouponsUsed.setTenantId(TokenUtils.currentTenantId());
            busMarketCouponsUsed.setHotelId(coupons.getHotelId());
            busMarketCouponsUsed.setCouponsId(dto.getCouponsId());
            busMarketCouponsUsed.setCode(randomNumber("MFJ"));
            busMarketCouponsUsed.setStatus(0);
            busMarketCouponsUsed.setCreateTime(DateTime.now());
            busMarketCouponsUsedList.add(busMarketCouponsUsed);
            dto.setNum(dto.getNum()-1);
        }
        this.saveBatch(busMarketCouponsUsedList);
        return Result.ok("创建成功");
    }

    /**
     * 发放免房券给非会员
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result gainCouponsUsedToNoMember(ProvideCouponsUsedDto dto) {
        if (ObjectUtils.isEmpty(dto.getCouponsId())) return Result.error("免房券id不能为空");
        if (dto.getNum() <= 0) return Result.error("每人发放张数不能小于1!");
        if (dto.getMobiles() == null || dto.getMobiles().size() <= 0) return Result.error("手机号不能为空!");
        BusMarketCoupons coupons = busMarketCouponsMapper.selectById(dto.getCouponsId());
        if (ObjectUtils.isEmpty(coupons)) {
            return Result.error("免房券活动不存在");
        }
        if (dto.getNum() > coupons.getKlqzs()) {
            return Result.error("每人最多可领取" + coupons.getKlqzs());
        }
        int totalNum = dto.getMobiles().size() * dto.getNum();

        LambdaQueryWrapper<BusMarketCouponsUsed> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BusMarketCouponsUsed::getStatus, CouponsStatusEnum.notClaimed.getKey());
        queryWrapper.eq(BusMarketCouponsUsed::getCouponsId, dto.getCouponsId());

        Page<BusMarketCouponsUsed> page = new Page<BusMarketCouponsUsed>(1, totalNum);
        IPage<BusMarketCouponsUsed> pageList = this.page(page, queryWrapper);
        int count = pageList.getRecords().size();
//        Long count= this.count(queryWrapper);
        if (totalNum > count) {
            return Result.error("待领取数量" + count + ",不够发放");
        }
        List<BusMarketCouponsUsed> list = pageList.getRecords();
        int index = 0;
//        AtomicReference<Boolean> isBreak = new AtomicReference<>(false);
        String message = "创建成功";
        try {
//            for (int i = 0; i < dto.getMobiles().size(); i++) {
//                int num = dto.getNum();
            //以防手机号相同用分组实现
            Map<String, List<MobileDto>> map = dto.getMobiles().stream().collect(Collectors.groupingBy(t -> t.getValue()));
            for (String key : map.keySet()) {
                int num = dto.getNum() * map.get(key).size();
                if (num > coupons.getKlqzs()) {
                    throw new JeecgBootException("每人最多可领取" + coupons.getKlqzs());
                }
                LambdaQueryWrapper<BusMemberCard> queryWrapper3 = new LambdaQueryWrapper<>();
                queryWrapper3.eq(BusMemberCard::getMobile, key);
                //查询手机号是否是会员
                BusMemberCard memeberCard = busMemberCardService.getOne(queryWrapper3);
                while (num > 0) {
                    LambdaQueryWrapper<BusMarketCouponsUsed> queryWrapper2 = new LambdaQueryWrapper<>();
                    queryWrapper2.eq(BusMarketCouponsUsed::getCouponsId, dto.getCouponsId());
//                    queryWrapper2.eq(BusMarketCouponsUsed::getMobile, dto.getMobiles().get(i).getValue());
                    queryWrapper2.eq(BusMarketCouponsUsed::getMobile, key);
                    Long gainCount = this.count(queryWrapper2);
                    if (gainCount > coupons.getKlqzs()) {
                        throw new JeecgBootException("每人限领数量" + coupons.getKlqzs());
                    }
                    BusMarketCouponsUsed model = list.get(index);
                    String keyString = String.format("sys:cache:couponsused::%s", model.getId());
                    if (redisUtil.hasKey(keyString)) {
//                        isBreak.set(true);
//                        break;
                        throw new JeecgBootException("该免房券已被领取，请勿同时操作该功能");
                    } else {
                        redisUtil.set(keyString, true);
                    }
                    //这里到时候要根据会员表查询一下是否存在会员信息，现在没有会员表
//                    model.setMobile(dto.getMobiles().get(i).getValue());
                    model.setMobile(key);
                    if (memeberCard != null) {
                        model.setUserName(memeberCard.getName());
                        model.setUserid(memeberCard.getId());
                    }
                    model.setGainTime(DateTime.now());
                    model.setStatus(CouponsStatusEnum.received.getKey());
                    index++;
                    num--;
                }
//                if (isBreak.get()) {
//                    //删除redis缓存
//                    list.forEach(item -> {
//                        String keyString = String.format("sys:cache:couponsused::%s", item.getId());
//                        redisUtil.del(keyString);
//                    });
//                    return Result.error("该免房券已被领取，请勿同时操作该功能");
//                }
            }

            this.updateBatchById(list);
        } catch (JeecgBootException ex) {
            message = ex.getMessage();
        } catch (Exception ex) {
            message = "创建失败";
        } finally {
            //删除redis缓存,添加成功后也可不删除
            list.forEach(item -> {
                String keyString = String.format("sys:cache:couponsused::%s", item.getId());
                redisUtil.del(keyString);
            });
        }
        return message == "创建成功" ? Result.ok(message) : Result.error(message);
    }


    /**
     * 发放免房券给会员
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result gainCouponsUsedToMember(ProvideCouponsUsedDto dto) {
        if (ObjectUtils.isEmpty(dto.getCouponsId())) return Result.error("免房券id不能为空");
        if (dto.getNum() <= 0) return Result.error("每人发放张数不能小于1!");
        if (dto.getMemberIds() == null || dto.getMemberIds().size() <= 0) return Result.error("会员不能为空!");
        BusMarketCoupons coupons = busMarketCouponsMapper.selectById(dto.getCouponsId());
        if (ObjectUtils.isEmpty(coupons)) {
            return Result.error("免房券活动不存在");
        }
        if (dto.getNum() > coupons.getKlqzs()) {
            return Result.error("每人最多可领取" + coupons.getKlqzs());
        }
        int totalNum = dto.getMemberIds().size() * dto.getNum();

        LambdaQueryWrapper<BusMarketCouponsUsed> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BusMarketCouponsUsed::getStatus, CouponsStatusEnum.notClaimed.getKey());
        queryWrapper.eq(BusMarketCouponsUsed::getCouponsId, dto.getCouponsId());

        Page<BusMarketCouponsUsed> page = new Page<BusMarketCouponsUsed>(1, totalNum);
        IPage<BusMarketCouponsUsed> pageList = this.page(page, queryWrapper);
        int count = pageList.getRecords().size();
        if (totalNum > count) {
            return Result.error("待领取数量" + count + ",不够发放");
        }
        List<BusMarketCouponsUsed> list = pageList.getRecords();
        int index = 0;
        String message = "创建成功";
        try {
            //以防会员相同用分组实现
            Map<String, List<String>> map=  dto.getMemberIds().stream().collect(Collectors.groupingBy(t->t));
            for (String key:map.keySet()) {
                int num = dto.getNum()*map.get(key).size();
                if (num> coupons.getKlqzs()) {
                    throw new JeecgBootException("每人最多可领取" + coupons.getKlqzs());
                }
                BusMemberCard memeberCard=busMemberCardService.getById(key);
                while (num > 0) {
                    LambdaQueryWrapper<BusMarketCouponsUsed> queryWrapper2 = new LambdaQueryWrapper<>();
                    queryWrapper2.eq(BusMarketCouponsUsed::getCouponsId, dto.getCouponsId());
                    queryWrapper2.and(i -> i.eq(BusMarketCouponsUsed::getUserid, key).or().eq(BusMarketCouponsUsed::getMobile, memeberCard.getMobile()));
                    Long gainCount = this.count(queryWrapper2);
                    if (gainCount > coupons.getKlqzs()) {
                        throw new JeecgBootException("每人限领数量" + coupons.getKlqzs());
                    }
                    BusMarketCouponsUsed model = list.get(index);
                    String keyString = String.format("sys:cache:couponsused::%s", model.getId());
                    if (redisUtil.hasKey(keyString)) {
                        throw new JeecgBootException("该免房券已被领取，请勿同时操作该功能");
                    } else {
                        redisUtil.set(keyString, true);
                    }
                    model.setUserid(memeberCard.getId());
                    model.setUserName(memeberCard.getName());
                    model.setMobile(memeberCard.getMobile());
                    model.setGainTime(DateTime.now());
                    model.setStatus(CouponsStatusEnum.received.getKey());
                    index++;
                    num--;
                }
            }

            this.updateBatchById(list);
        } catch (JeecgBootException ex) {
            message = ex.getMessage();
        } catch (Exception ex) {
            message = "创建失败";
        } finally {
            //删除redis缓存,添加成功后也可不删除
            list.forEach(item -> {
                String keyString = String.format("sys:cache:couponsused::%s", item.getId());
                redisUtil.del(keyString);
            });
        }
        return message == "创建成功" ? Result.ok(message) : Result.error(message);
    }
}
